﻿using System.Collections.Generic;
using System.Xml.Linq;
using System.IO;
using System.Text;
using System.Xml;
using System.Linq;

namespace Gestalt
{
    public partial class Filters
    {
        Dictionary<string, string> xamlTerms = new Dictionary<string, string>();

        public Filters()
        {
            string[] xaml = ReservedWords();

            foreach (string term in xaml) xamlTerms.Add(term.ToLower(), term);
        }

        public string Filter(string xml)
        {
            // transform input to output, fixing XML that was molested by Firefox
            try
            {
                XDocument doc = XDocument.Load(new StringReader(xml));
                XElement root = (XElement)Filter((XNode)doc.Root);

                StringBuilder sb = new StringBuilder();

                XmlWriter w = XmlWriter.Create(new StringWriter(sb));
                root.WriteTo(w);
                w.Flush();

                return sb.ToString();
            }
            catch (XmlException e)
            {
                string errorMsg = "Syntax error parsing the embedded XAML.  This is probably an unterminated XML issue in Firefox/Chrome/Safari.  <a href='http://visitmix.com/labs/gestalt/faqs.html'>See the FAQ</a> for workarounds to known issues.  The error message was:\r\n";
                int inner = e.Message.IndexOf("--- Inner Exception");
                if (inner > 1)
                {
                    errorMsg += e.Message.Substring(0, inner);
                }
                else
                {
                    errorMsg += e.Message;
                }
                GestaltApp.reportError(errorMsg);
                return null;

            }
        }

        public XNode Filter(XNode node)
        {
            if (node is XElement)
            {
                XElement xe = (XElement)node;
                return new XElement(Filter(xe.Name),
                    from attr in xe.Attributes()
                    where attr.Name == "xmlns"
                    select attr,
                    from attr in xe.Attributes()
                    where attr.Name != "xmlns"
                    select new XAttribute(Filter(attr.Name), attr.Value),
                    from xn in xe.Nodes() where xn is XElement || xn is XText select Filter(xn)
                    );
            }
            else return node;
        }


        public XName Filter(XName name)
        {
            XName newname;

            if (name.LocalName.Length == 1)
            {
                newname = name.Namespace + name.LocalName.ToUpper();
            }
            else
            {
                newname = name.Namespace + FilterString(name.LocalName);
            }


            return newname;
        }

        public string FilterString(string localname)
        {
            var delim = new char[] { '.' };
            var parts = localname.Split(delim);

            if (parts.Length > 1)
                return string.Join(".", (from p in parts select FilterString(p)).ToArray());
            else
            {
                if (xamlTerms.ContainsKey(localname.ToLower()))
                    return xamlTerms[localname.ToLower()];
                //else if (xamlTerms.ContainsKey(localname.ToLower().Replace("property","")))
                //{
                //    return localname.ToLower().Replace("property", "") + "Property";
                //}
                //else if (localname.ToLower() == localname && localname.Contains("property"))
                //{
                //    localname = localname.Replace("property", "");
                //    return (localname.Substring(0, 1).ToUpper() + localname.Substring(1, localname.Length - 1)) + "Property";
                //}
                else if (localname.ToLower() == localname)
                {
                    return (localname.Substring(0, 1).ToUpper() + localname.Substring(1, localname.Length - 1));
                }
                else return localname;
            }
        }

    }
}
